package com.blue.waffle.iwc.screens;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.g2d.ParticleEffect;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Touchable;
import com.badlogic.gdx.scenes.scene2d.ui.CheckBox;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Slider;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
import com.badlogic.gdx.scenes.scene2d.utils.ActorGestureListener;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.blue.waffle.iwc.game.IWCGame;
import com.blue.waffle.iwc.screens.OptionsScreen.OptionsButtonListener.OptionsButton;
import com.blue.waffle.iwc.ui.ButtonActorListener;
import com.blue.waffle.iwc.ui.ParallaxBackground;
import com.blue.waffle.iwc.ui.ParallaxLayer;
import com.blue.waffle.iwc.utils.SoundManager.IWCSound;
import com.blue.waffle.iwc.utils.SoundsManager;

public class OptionsScreen extends AbstractScreen {

	private static final float ROWS = 4;
	private static final int COLS = 4;
	private Window window;

	public OptionsScreen(IWCGame game) {
		super(game);
	}

	@Override
	public void show() {
		super.show();
		Skin skin = getUiSkin();
		
		ParticleEffect bubbleEffect=game.getAssetManager().get("effects/bubble.particle",ParticleEffect.class);
		setParticleEffect(bubbleEffect);
		
		window = new Window("Options", skin);
		gameStage.addActor(window);
		window.setMovable(false);
		window.setBounds(WINDOW_PADDINGS, WINDOW_PADDINGS,
				IWCGame.VIRTUAL_WIDTH - WINDOW_PADDINGS * 2,
				IWCGame.VIRTUAL_HEIGHT - WINDOW_PADDINGS * 2);
		window.defaults().fill().padBottom(CELL_PADDINGS);
		
		float rowHeight = (window.getHeight()-40) / ROWS - CELL_PADDINGS * 2;
		
		// new row
		window.row().height(rowHeight).fillX();

		// setup music slider
		setupSlider(0, 1f, 0.1f, game.getMusicManager().getVolume(), true, game
				.getMusicManager().isActive(), skin);

		// new row
		window.row().height(rowHeight);

		// setup sound slider
		setupSlider(0, 1f, 0.1f, game.getSoundManager().getVolume(), false,
				game.getSoundManager().isActive(), skin);

		// new row
		window.row().height(rowHeight);

		// setup user profile button
		TextButton manageUserProfileButton = new TextButton(
				"Manage User Profiles", skin);
		window.add(manageUserProfileButton).height(rowHeight).colspan(COLS)
				.fillX();
		
		// new row
		window.row().height(rowHeight);

		// setup custom dictionary button
		TextButton addDictionaryButton = new TextButton(
				"Add custom dictionary", skin);
		addDictionaryButton.addListener(new OptionsButtonListener(this, OptionsButton.IMPORT_DICTIONARY));
		window.add(addDictionaryButton).height(rowHeight).colspan(COLS)
				.fillX();

		gameStage.addActor(getButtonTable(skin,new OptionsButtonListener(this, OptionsButton.BACK)).right().bottom());
		//window.debug();
	}

	/**
	 * A wrapper method to setup the sound slider controls.
	 * 
	 * @param min
	 *            -the minimum value
	 * @param max
	 *            -the maximum value
	 * @param step
	 *            -the sliding step
	 * @param value
	 *            -the current value to set
	 * @param isMusic
	 *            -indicates whether or not the section if for music setting
	 * @param isActive
	 *            -indicates if the setting is active
	 * @param skin
	 *            -the required skin object
	 */
	private void setupSlider(float min, float max, float step, float value,
			final boolean isMusic, boolean isActive, Skin skin) {
		final Slider soundSlider = new Slider(min, max, step, false, skin);
		final Label soundVolumeLb = new Label(value * 10 + "", skin);
		soundSlider.setValue(value);
		soundSlider.setTouchable(isActive ? Touchable.enabled
				: Touchable.disabled);
		soundSlider.addListener(new ChangeListener() {

			@Override
			public void changed(ChangeEvent event, Actor actor) {
				game.getSoundManager().play(IWCSound.TICK);
				float volume = soundSlider.getValue();
				soundVolumeLb.setText(volume * 10 + "");
				if (isMusic) {
					game.getMusicManager().setVolume(volume);
					game.getPreferencesManager().setMusicVolume(volume);
				} else {
					game.getSoundManager().setVolume(volume);
					game.getPreferencesManager().setSoundVolume(volume);
				}

			}
		});

		final CheckBox activeCheckBox = new CheckBox("Active", skin);
		activeCheckBox.setChecked(isActive);
		activeCheckBox.addListener(getActiveChangeListener(soundSlider,
				soundVolumeLb, isMusic));
		window.add(isMusic ? "Music:" : "Sound:").width(100);
		window.add(soundSlider).width(320);
		window.add(soundVolumeLb).width(50);
		window.add(activeCheckBox).width(130);
	}

	/**
	 * Returns a {@link ChangeListener} to handle the checked state for each
	 * corresponding volume setting.
	 * 
	 * @param slider
	 *            -the volume slider
	 * @param volumeLb
	 *            -the volume label
	 * @param isMusic
	 *            -indicates if the slider is for music volume
	 * @return
	 */
	private ChangeListener getActiveChangeListener(final Slider slider,
			final Label volumeLb, final boolean isMusic) {
		return new ChangeListener() {
			@Override
			public void changed(ChangeEvent event, Actor actor) {

				CheckBox activeCheckBox = (CheckBox) actor;
				boolean active = activeCheckBox.isChecked();
				float volume = slider.getValue();
				SoundsManager soundsManager = null;

				if (isMusic) {
					soundsManager = game.getMusicManager();
				} else {
					soundsManager = game.getSoundManager();
				}

				if (active) {
					volume = SoundsManager.DEFAULT_VOLUME;
				} else {
					volume = 0f;
				}
				soundsManager.setVolume(volume);
				soundsManager.setActive(active);
				

				if (isMusic) {
					game.getPreferencesManager().setMusicActive(active);
					game.getPreferencesManager().setMusicVolume(volume);
				} else {
					game.getPreferencesManager().setSoundActive(active);
					game.getPreferencesManager().setSoundVolume(volume);
				}

				slider.setValue(volume);
				slider.setTouchable(active ? Touchable.enabled
						: Touchable.disabled);
				volumeLb.setText(volume * 10 + "");

			}
		};
	}
	

	
	@Override
	public boolean keyDown(int keycode) {
		if (Gdx.input.isKeyPressed(Keys.BACK)) {
			game.setScreen(new MenuScreen(game));
			return true;
		}
		return super.keyDown(keycode);
	}
	

	/**
	 * A wrapper class that extends the {@link ActorGestureListener} to provide
	 * a way to customize different button click events.
	 * 
	 * @author Wenbin
	 * 
	 */
	public static class OptionsButtonListener extends ButtonActorListener {

		public enum OptionsButton  {
			USER_PROFILES, IMPORT_DICTIONARY, BACK, OK, CANCEL
		};

		private OptionsButton button;

		public OptionsButtonListener(AbstractScreen screen, OptionsButton button) {
			super(screen);
			this.button = button;
		}

		@Override
		public void clicked(InputEvent event, float x, float y) {
			super.clicked(event, x, y);
			IWCGame iwcGame = screen.game;
			switch (this.button) {
			case BACK:
				iwcGame.setScreen(new MenuScreen(iwcGame));
				break;
			case IMPORT_DICTIONARY:
				iwcGame.setScreen(new DictionaryScreen(iwcGame, IWCGame.getAPP_FILE_DIR()));
				break;
			default:
				break;
			}
		}
	}
	
}
